home *** CD-ROM | disk | FTP | other *** search
- /* $Id: lcmp.c,v 1.1 1992/11/10 05:22:10 david Exp $
- *
- * lcmp.c -- Compare two lists for equality.
- *
- * AUTHOR: David Herron <david@twg.com> (work) or <david@davids.mmdf.com> (home)
- *
- * $Log: lcmp.c,v $
- * Revision 1.1 1992/11/10 05:22:10 david
- * Initial revision.
- *
- *
- */
-
- #include <tcl.h>
-
- /*
- * USAGE: lcompare list1 list2
- *
- * The following is worlds faster than the closest we can get
- * with TCL, namely:
- *
- * proc lcompare {list1 list2} {
- * set l1_len [llength $list1]
- * set l2_len [llength $list2]
- * if {$l1_len < $l2_len} { return -1 }
- * if {$l1_len > $l2_len} { return 1 }
- * set i 0
- * foreach e1 $list1 {
- * set e2 [lindex $list2]
- * if {$e1 == $e2} continue
- * if {$e1 < $e2} { return -1 }
- * if {$e1 > $e2} { return 1 }
- * }
- * return 0
- * }
- *
- * The advantage the C code has is it only has to parse each
- * list once. The above parses list1 twice, and list2 many
- * times.
- *
- * RETURN VALUES:
- *
- * -1 List 1 is shorter than list 2.
- * OR An element of list 1 is "less than" the matching
- * element of list 2.
- *
- * 0 They have the same number of elements AND
- * all elements are equal.
- *
- * 1 List 1 is longer than list 2.
- * OR an element of list 1 is "greater than" the
- * matching element of list2.
- *
- * "less than", "equal" and "greater than" are as determined by strcmp(3).
- *
- *
- * TODO:
- *
- * - Add a fourth argument to be a command string to execute.
- * - Or some other way the programmer could customize the comparison.
- */
-
-
- static int
- cmdListCompare(clientData, interp, argc, argv)
- ClientData *clientData;
- Tcl_Interp *interp;
- int argc;
- char *argv[];
- {
- int l1_argc, l2_argc;
- char **l1_argv = (char **)NULL, **l2_argv = (char **)NULL;
-
- if (argc != 3) {
- Tcl_AppendResult(interp, "USAGE: lcompare list1 list2", NULL);
- return TCL_ERROR;
- }
-
- if (Tcl_SplitList(interp, argv[1], &l1_argc, &l1_argv) == TCL_ERROR)
- return TCL_ERROR;
-
- if (Tcl_SplitList(interp, argv[2], &l2_argc, &l2_argv) == TCL_ERROR) {
- if (l1_argv) free(l1_argv);
- return TCL_ERROR;
- }
-
- if (l1_argc < l2_argc) Tcl_SetResult(interp, "-1", TCL_STATIC);
- else if (l1_argc > l2_argc) Tcl_SetResult(interp, "1", TCL_STATIC);
- else {
- int i, cmpval;
- for (i=0; i < l1_argc; i++) {
- cmpval = strcmp(l1_argv[i], l2_argv[i]);
- if (cmpval == 0) continue;
- if (cmpval < 0) Tcl_SetResult(interp, "-1", TCL_STATIC);
- if (cmpval > 0) Tcl_SetResult(interp, "1", TCL_STATIC);
- goto all_done;
- }
- Tcl_SetResult(interp, "0", TCL_STATIC);
- }
-
- all_done:
- if (l1_argv) free(l1_argv);
- if (l2_argv) free(l2_argv);
-
- return TCL_OK;
- }
-
- void
- init_lcompare(interp)
- Tcl_Interp *interp;
- {
- Tcl_CreateCommand(interp, "lcompare", cmdListCompare, (ClientData) NULL,
- (Tcl_CmdDeleteProc *) NULL);
- }
-
-